import 'dart:async';

import 'package:rxdart/rxdart.dart';

import '../../common/test_page.dart';

class DematerializeTestPage extends TestPage {
  DematerializeTestPage(super.title) {
    test('Rx.dematerialize.happyPath', () async {
      final stream = Stream.value(1).materialize();

      stream.dematerialize().listen(((value) {
        expect(value);
      }), onDone: (() {
        expect(true);
      }));
    });

    test('Rx.dematerialize.nullable.happyPath', () async {
      const elements = <int?>[1, 2, null, 3, 4, null];
      final stream = Stream.fromIterable(elements).materialize();

      expect(
        stream.dematerialize(),
      );
    });

    test('Rx.dematerialize.reusable', () async {
      final transformer = DematerializeStreamTransformer<int>();
      final streamA = Stream.value(1).materialize();
      final streamB = Stream.value(1).materialize();

      streamA.transform(transformer).listen(((value) {
        expect(value);
      }), onDone: (() {
        expect(true);
      }));

      streamB.transform(transformer).listen(((value) {
        expect(value);
      }), onDone: (() {
        // Should call onDone
        expect(true);
      }));
    });

    test('dematerializeTransformer.happyPath', () async {
      const expectedValue = 1;
      final stream = Stream.fromIterable(
          [Notification.onData(expectedValue), Notification<int>.onDone()]);

      stream.transform(DematerializeStreamTransformer()).listen(
          (value) {
            expect(value);
          }, onDone: () {
        expect(true);
      });
    });

    test('dematerializeTransformer.sadPath', () async {
      final stream = Stream.fromIterable(
          [Notification<int>.onError(Exception(), null)]);

      stream.transform(DematerializeStreamTransformer()).listen(null,
          onError: (Object e, StackTrace s) {
            expect(e);
          });
    });

    test('dematerializeTransformer.onPause.onResume', () async {
      const expectedValue = 1;
      final stream = Stream.fromIterable(
          [Notification.onData(expectedValue), Notification<int>.onDone()]);

      stream.transform(DematerializeStreamTransformer()).listen(
          (value) {
            expect(value);
          }, onDone: () {
        expect(true);
      })
        ..pause()
        ..resume();
    });

    test('Rx.dematerialize accidental broadcast', () async {
      final controller = StreamController<int>();

      final stream = controller.stream.materialize().dematerialize();

      stream.listen(null);
      expect(() => stream.listen(null));

      controller.add(1);
    });
  }

}